package com.dlc.shop.service.impl;

import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dlc.shop.allinpay.service.AllinpayCompanyService;
import com.dlc.shop.bean.enums.ShopWalletAmountType;
import com.dlc.shop.bean.enums.ShopWalletChangeReason;
import com.dlc.shop.bean.model.ShopWallet;
import com.dlc.shop.bean.model.ShopWalletLog;
import com.dlc.shop.bean.param.CustomerReqParam;
import com.dlc.shop.common.allinpay.constant.PaySysType;
import com.dlc.shop.common.i18n.I18nMessage;
import com.dlc.shop.common.util.Arith;
import com.dlc.shop.common.util.PageParam;
import com.dlc.shop.common.util.PoiExcelUtil;
import com.dlc.shop.dao.ShopWalletLogMapper;
import com.dlc.shop.service.ShopWalletLogService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import org.apache.poi.ss.usermodel.Sheet;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 商家钱包记录
 *
 * @author Dwl
 * @date 2019-09-19 14:02:57
 */
@Service
@AllArgsConstructor
public class ShopWalletLogServiceImpl extends ServiceImpl<ShopWalletLogMapper, ShopWalletLog> implements ShopWalletLogService {

    private final ShopWalletLogMapper shopWalletLogMapper;
    private final AllinpayCompanyService allinpayCompanyService;


    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void saveShopWalletLog(ShopWallet oldShopWallet, ShopWallet newShopWallet, ShopWalletChangeReason shopWalletChangeReason, String orderNumber) {

        ShopWalletLog shopWalletLog = new ShopWalletLog();

        shopWalletLog.setCreateTime(new Date());
        shopWalletLog.setPaySysType(oldShopWallet.getPaySysType());
        shopWalletLog.setOrderNumber(orderNumber);
        shopWalletLog.setReason(shopWalletChangeReason.value());
        shopWalletLog.setShopId(oldShopWallet.getShopId());
        // 插入未结算金额修改记录
        if (!Objects.equals(oldShopWallet.getUnsettledAmount(), newShopWallet.getUnsettledAmount())) {
            double changeAmount = Arith.sub(oldShopWallet.getUnsettledAmount(), newShopWallet.getUnsettledAmount());
            shopWalletLog.setChangeAomunt(oldShopWallet.getUnsettledAmount() > newShopWallet.getUnsettledAmount() ? changeAmount : -changeAmount);
            shopWalletLog.setIoType(oldShopWallet.getUnsettledAmount() > newShopWallet.getUnsettledAmount() ? 0 : 1);
            shopWalletLog.setAmountType(ShopWalletAmountType.UNSETTLED_AMOUNT.value());
            shopWalletLogMapper.insert(shopWalletLog);
        }

        // 插入结算金额修改记录
        if (!Objects.equals(oldShopWallet.getSettledAmount(), newShopWallet.getSettledAmount())) {
            double changeAmount = Arith.sub(oldShopWallet.getSettledAmount(), newShopWallet.getSettledAmount());
            shopWalletLog.setChangeAomunt(oldShopWallet.getSettledAmount() > newShopWallet.getSettledAmount() ? changeAmount : -changeAmount);
            shopWalletLog.setIoType(oldShopWallet.getSettledAmount() > newShopWallet.getSettledAmount() ? 0 : 1);
            shopWalletLog.setAmountType(ShopWalletAmountType.SETTLED_AMOUNT.value());
            shopWalletLog.setWalletLogId(null);
            shopWalletLogMapper.insert(shopWalletLog);
        }

        // 插入冻结金额修改记录
        if (!Objects.equals(oldShopWallet.getFreezeAmount(), newShopWallet.getFreezeAmount())) {
            double changeAmount = Arith.sub(oldShopWallet.getFreezeAmount(), newShopWallet.getFreezeAmount());
            shopWalletLog.setChangeAomunt(oldShopWallet.getFreezeAmount() > newShopWallet.getFreezeAmount() ? changeAmount : -changeAmount);
            shopWalletLog.setIoType(oldShopWallet.getFreezeAmount() > newShopWallet.getFreezeAmount() ? 0 : 1);
            shopWalletLog.setAmountType(ShopWalletAmountType.FREEZE_AMOUNT.value());
            shopWalletLog.setWalletLogId(null);
            shopWalletLogMapper.insert(shopWalletLog);
        }

//        // 插入总结算金额记录
//        if (!Objects.equals(oldShopWallet.getTotalSettledAmount(), newShopWallet.getTotalSettledAmount())) {
//            double changeAmount = Arith.sub(oldShopWallet.getTotalSettledAmount(), newShopWallet.getTotalSettledAmount());
//            shopWalletLog.setChangeAomunt(oldShopWallet.getTotalSettledAmount() > newShopWallet.getTotalSettledAmount() ? changeAmount: -changeAmount);
//            shopWalletLog.setBeforeAmount(oldShopWallet.getTotalSettledAmount());
//            shopWalletLog.setAfterAmount(newShopWallet.getTotalSettledAmount());
//            shopWalletLog.setIoType(oldShopWallet.getTotalSettledAmount() > newShopWallet.getTotalSettledAmount() ? 0 : 1);
//            shopWalletLog.setAmountType(ShopWalletAmountType.TOTAL_SETTLED_AMOUNT.value());
//            shopWalletLogMapper.insert(shopWalletLog);
//        }
    }

    @Override
    public IPage<ShopWalletLog> pageByParam(PageParam<ShopWalletLog> page, ShopWalletLog shopWalletLog) {
        Integer paySysType = allinpayCompanyService.getIsAllinpay() ? PaySysType.ALLINPAY.value() : PaySysType.DEFAULT.value();
        shopWalletLog.setPaySysType(paySysType);
        return shopWalletLogMapper.listByParam(page, shopWalletLog);
    }

    @Override
    public IPage<ShopWalletLog> pageAllShop(PageParam<ShopWallet> page, ShopWalletLog shopWalletLog) {
        Integer paySysType = allinpayCompanyService.getIsAllinpay() ? PaySysType.ALLINPAY.value() : PaySysType.DEFAULT.value();
        shopWalletLog.setPaySysType(paySysType);
        return shopWalletLogMapper.pageAllByParam(page, shopWalletLog);
    }

    @Override
    public void excelShopWalletLog(CustomerReqParam customerReqParam, HttpServletResponse response) {
        Integer paySysType = allinpayCompanyService.getIsAllinpay() ? PaySysType.ALLINPAY.value() : PaySysType.DEFAULT.value();
        customerReqParam.setPaySysType(paySysType);
        List<ShopWalletLog> shopWalletLogs = shopWalletLogMapper.listShopWalletLogByParam(customerReqParam);
        ExcelWriter writer = ExcelUtil.getBigWriter();
        String[] headers = {
                I18nMessage.getMessage("yami.shop.wallet.log.excel.header.seq"),
                I18nMessage.getMessage("yami.shop.wallet.log.excel.header.shopName"),
                I18nMessage.getMessage("yami.shop.wallet.log.excel.header.amountType"),
                I18nMessage.getMessage("yami.shop.wallet.log.excel.header.incomeType"),
                I18nMessage.getMessage("yami.shop.wallet.log.excel.header.changeAmount"),
                I18nMessage.getMessage("yami.shop.wallet.log.excel.header.orderNumber"),
                I18nMessage.getMessage("yami.shop.wallet.log.excel.header.refundNumber"),
                I18nMessage.getMessage("yami.shop.wallet.log.excel.header.operateAmount"),
                I18nMessage.getMessage("yami.shop.wallet.log.excel.header.platformAmount"),
                I18nMessage.getMessage("yami.shop.wallet.log.excel.header.shopAmount"),
                I18nMessage.getMessage("yami.shop.wallet.log.excel.header.distributeAmount"),
                I18nMessage.getMessage("yami.shop.wallet.log.excel.header.platformCommission"),
                I18nMessage.getMessage("yami.shop.wallet.log.excel.header.fundChangeReason"),
                I18nMessage.getMessage("yami.shop.wallet.log.excel.header.createTime")
        };
        List<String> headerList = Arrays.asList(headers);
        writer.merge(headerList.size() - 1, I18nMessage.getMessage("yami.shop.wallet.log.excel"));
        writer.writeRow(headerList);
        Sheet sheet = writer.getSheet();
        for (int i = 1; i < headerList.size(); i++) {
            sheet.setColumnWidth(i, 20 * 256);
        }
        int row = 1;
        for (ShopWalletLog shopWalletLog : shopWalletLogs) {
            int firstRow = ++row;
            int col = -1;
            PoiExcelUtil.mergeIfNeed(writer, firstRow, firstRow, ++col, col, row - 1);
            PoiExcelUtil.mergeIfNeed(writer, firstRow, firstRow, ++col, col, shopWalletLog.getShopName());
            ShopWalletAmountType amountType = ShopWalletAmountType.instance(shopWalletLog.getAmountType());
            PoiExcelUtil.mergeIfNeed(writer, firstRow, firstRow, ++col, col, Objects.isNull(amountType) ? "" : I18nMessage.getMessage(amountType.getI18nTag()));
            PoiExcelUtil.mergeIfNeed(writer, firstRow, firstRow, ++col, col, shopWalletLog.getIoType().equals(1) ? I18nMessage.getMessage("yami.finance.income") : I18nMessage.getMessage("yami.finance.pay"));
            PoiExcelUtil.mergeIfNeed(writer, firstRow, firstRow, ++col, col, shopWalletLog.getChangeAomunt());
            PoiExcelUtil.mergeIfNeed(writer, firstRow, firstRow, ++col, col, shopWalletLog.getOrderNumber());
            PoiExcelUtil.mergeIfNeed(writer, firstRow, firstRow, ++col, col, shopWalletLog.getRefundSn());
            PoiExcelUtil.mergeIfNeed(writer, firstRow, firstRow, ++col, col, shopWalletLog.getUserAmount());
            PoiExcelUtil.mergeIfNeed(writer, firstRow, firstRow, ++col, col, shopWalletLog.getPlatformAmount());
            PoiExcelUtil.mergeIfNeed(writer, firstRow, firstRow, ++col, col, shopWalletLog.getShopReduceAmount());
            PoiExcelUtil.mergeIfNeed(writer, firstRow, firstRow, ++col, col, shopWalletLog.getDistributionAmount());
            PoiExcelUtil.mergeIfNeed(writer, firstRow, firstRow, ++col, col, shopWalletLog.getPlatformCommission());
            ShopWalletChangeReason reason = ShopWalletChangeReason.instance(shopWalletLog.getReason());
            PoiExcelUtil.mergeIfNeed(writer, firstRow, firstRow, ++col, col, Objects.isNull(reason) ? "" : I18nMessage.getMessage(reason.getI18nTag()));
            PoiExcelUtil.mergeIfNeed(writer, firstRow, firstRow, ++col, col, shopWalletLog.getCreateTime());
        }
        PoiExcelUtil.writeExcel(response, writer);
    }
}
